<?php
/**
 * Defines Kodform class
 *
 *
 * @copyright 	Copyright (c) 2007 Boris Tomic (kodmasin.net)
 * @category 	Kodform
 * @package 	Kodform
 * @author 		Boris Tomic
 * @license 	http://boris.kodmasin.net/kodform4:license The BSD License
 *
 */

require_once 'Kodform/Exception.php';
require_once 'Kodform/Validator.php';
require_once 'Kodform/Filter.php';

//TODO testovi

/**
 * class which implements validation
 * 
 * it can validate more values at same time with different validators. this
 * is veri usefull when you are validating POSTs or GETs arrays.
 * 
 */
class Kodvalid {
	private $values;
	private $errors;
	private $validators;
	private $names;
	private $validated;
	private $filters;
	private $validated_values;
	/**
	 * in constructor you have to devine names (keys) for values you are interested to validate
	 *
	 * @param array $names array with names (keys) of values to validate
	 */
	function __construct(array $names){
		$this->values = null;
		$this->names = $names;
		$this->errors = array();
		$this->validators = array();
		$this->validated = false;
		$this->filters = array();
		$this->validated_values = array(); 
	}
	/**
	 * add new validator for some value
	 *
	 * @param string $valueName name of the value that should have this validator
	 * @param Kodform_Validator $validator validator which will be used
	 * @return Kodvalid returns object of this method (that way you can cll this method faster)
	 */
	public function &addValidator($valueName, Kodform_Validator &$validator){
		if(!in_array($valueName, $this->names))
			throw new Kodform_Exception("There is no value under name '" . $valueName . "' in this validator.");
		if(!isset($this->validators[$valueName]))
			$this->validators[$valueName] = array();
		$this->validators[$valueName][] = $validator;
		$this->validated = false;
		return $this;
	}
	/**
	 * set filter to values. order of setting filters for a value can be inportan to be carefull 
	 *
	 * @param string $valueName name if value (key)
	 * @param Kodform_Filter $filter filter 
	 * @return Kodvalid returns object of this method (that way you can cll this method faster)
	 */
	public function &addFilter($valueName, Kodform_Filter &$filter){
		if(!in_array($valueName, $this->names))
			throw new Kodform_Exception("There is no value under name '" . $valueName . "' in this validator.");
		if(!isset($this->filters[$valueName]))
			$this->filters[$valueName] = array();
		$this->filters[$valueName][] = $filter;
		$this->validated = false;
		return $this;
	}
	/**
	 * validate all values with all validators
	 *
	 * @return boolean if all alues are valid returns true otherwise false
	 */
	function validate(){
		if($this->values === null){
			throw Kodform_Exception("Could not validate because there are no data to validate.");
		}
		foreach($this->names as $name){
			$this->validated_values[$name] = $this->values[$name];
			if(isset($this->filters[$name])){
				foreach($this->filters[$name] as $filter){
					$this->validated_values[$name] = $filter->filter($this->validated_values[$name]);
				}
			}
			//$valid = true;
			//var_dump($this->validators);
			if(isset($this->validators[$name])){
				foreach($this->validators[$name] as $validator){
					if(!$validator->validate($this->validated_values[$name])){
						//$valid = false;
						if(!isset($this->errors[$name]))
							$this->errors[$name] = array();
						$this->errors[$name][] = $validator->getError();
					}
				}
			}
		}
		$this->validated = true;
		return $this->isAllValid();
	}
	/**
	 * set valuse to be validate
	 *
	 * @param array $values arry which contains values which are itentified by keys as names. ex. $_POST valiable
	 * @return Kodvalid returns object of this method (that way you can cll this method faster) 
	 */
	function setValues(array $values){
		$this->values = $values;
		$this->validated = false;
		return $this;
	}
	/**
	 * return all errors connected with one value idetified by name (key)
	 *
	 * @param string $valueName name which identifies value
	 * @return array which contains all errors
	 */
	function getErrors($valueName){
		if(!in_array($valueName, $this->names)){
			throw new Kodform_Exception("There is no value under name '" . $valueName . "' in this validator.");
		}
		if(!$this->validated)
			$this->validate();
		return $this->errors[$valueName];
	}
	/**
	 * returns all errors of all values which had not passed validation 
	 *
	 * @return array which conatins all errors
	 */
	function getAllErrors(){
		if(!$this->validated)
			$this->validate();
		return $this->errors;
	}
	/**
	 * use this to see is only one value valid or not 
	 *
	 * @param string $valueName value name (key)
	 * @return boolean ifit is valid true if not valid false
	 */
	function isValid($valueName){
		if(!in_array($valueName, $this->names))
			throw new Kodform_Exception("There is no value under name '" . $valueName . "' in this validator.");
		if(!$this->validated)
			$this->validate();
		if(in_array(array_key_exists($valueName, $this->errors)))
			return false;
		return true;
	}
	/**
	 * call to chack are all values valid or not
	 *
	 * @return boolean if thaere are then true if not false
	 */
	function isAllValid(){
		if(!$this->validated)
			$this->validate();
		if(count($this->errors) == 0)
			return true;
		return false;
	}
	/**
	 * returns filtered and validated values or null if values are not valid
	 *
	 * @return mixed array if all values are valid or null if they are not valid
	 */
	public function getValues(){
		if(!$this->validated)
			$this->validate();
		if($this->isAllValid())
			return $this->validated_values;
		return null;
	}
}